//*****************************************************************************
//
// startup_gcc.c - Startup code for use with GNU tools.
//
// Copyright (c) 2007-2008 Luminary Micro, Inc.  All rights reserved.
//
// Software License Agreement
//
// Luminary Micro, Inc. (LMI) is supplying this software for use solely and
// exclusively on LMI's microcontroller products.
//
// The software is owned by LMI and/or its suppliers, and is protected under
// applicable copyright laws.  All rights are reserved.  You may not combine
// this software with "viral" open-source software in order to form a larger
// program.  Any use in violation of the foregoing restrictions may subject
// the user to criminal sanctions under applicable laws, as well as to civil
// liability for the breach of the terms and conditions of this license.
//
// THIS SOFTWARE IS PROVIDED "AS IS".  NO WARRANTIES, WHETHER EXPRESS, IMPLIED
// OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
// LMI SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
// CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
//
// This is part of revision 2752 of the Stellaris Peripheral Driver Library.
//
//*****************************************************************************

//*****************************************************************************
//
// Forward declaration of the default fault handlers.
//
//*****************************************************************************
void ResetISR(void);
static void NmiSR(void);
static void FaultISR(void);
static void IntDefaultHandler(void);

// External interrupt handlers
extern void EthernetIntHandler();
extern void SysTickIntHandler();
extern void ADCIntHandler();
extern void UARTIntHandler();


#include "hw_memmap.h"
#include "platform_conf.h"

#if defined( BUILD_CAN )
extern void CANIntHandler();
#endif

extern void uart0_handler();
extern void uart1_handler();
extern void uart2_handler();
extern void gpioa_handler();
extern void gpiob_handler();
extern void gpioc_handler();
extern void gpiod_handler();
extern void gpioe_handler();
extern void gpiof_handler();
extern void gpiog_handler();
extern void gpioh_handler();
extern void gpioj_handler();
extern void tmr0_handler();
extern void tmr1_handler();
extern void tmr2_handler();
extern void tmr3_handler();
#if defined( BUILD_USB_CDC )
extern void USB0DeviceIntHandler(void);
#endif

// From platform.c
extern const u32 uart_base[];

//*****************************************************************************
//
// The entry point for the application.
//
//*****************************************************************************
extern int main(void);

//*****************************************************************************
//
// The vector table.  Note that the proper constructs must be placed on this to
// ensure that it ends up at physical address 0x0000.0000.
//
//*****************************************************************************
__attribute__ ((section(".isr_vector")))
void (* const g_pfnVectors[])(void) =
{
    (void (*) (void))( SRAM_BASE + SRAM_SIZE ),
                                            // The initial stack pointer
    ResetISR,                               // The reset handler
    NmiSR,                                  // The NMI handler
    FaultISR,                               // The hard fault handler
    IntDefaultHandler,                      // The MPU fault handler
    IntDefaultHandler,                      // The bus fault handler
    IntDefaultHandler,                      // The usage fault handler
    0,                                      // Reserved
    0,                                      // Reserved
    0,                                      // Reserved
    0,                                      // Reserved
    IntDefaultHandler,                      // SVCall handler
    IntDefaultHandler,                      // Debug monitor handler
    0,                                      // Reserved
    IntDefaultHandler,                      // The PendSV handler
    SysTickIntHandler,                      // The SysTick handler
    gpioa_handler,                          // GPIO Port A
    gpiob_handler,                          // GPIO Port B
    gpioc_handler,                          // GPIO Port C
    gpiod_handler,                          // GPIO Port D
    gpioe_handler,                          // GPIO Port E
#if defined( BUILD_C_INT_HANDLERS ) || defined( BUILD_LUA_INT_HANDLERS )
    uart0_handler,                          // UART0 Rx and Tx
#else
    IntDefaultHandler,
#endif
#if defined( BUILD_C_INT_HANDLERS ) || defined( BUILD_LUA_INT_HANDLERS )
    uart1_handler,                          // UART1 Rx and Tx
#else
    IntDefaultHandler,                      // UART1 Rx and Tx
#endif    
    IntDefaultHandler,                      // SSI0 Rx and Tx
    IntDefaultHandler,                      // I2C0 Master and Slave
    IntDefaultHandler,                      // PWM Fault
    IntDefaultHandler,                      // PWM Generator 0
    IntDefaultHandler,                      // PWM Generator 1
    IntDefaultHandler,                      // PWM Generator 2
    IntDefaultHandler,                      // Quadrature Encoder 0
#ifdef BUILD_ADC
    ADCIntHandler,	                        // ADC Sequence 0
    ADCIntHandler,                          // ADC Sequence 1
    ADCIntHandler,                          // ADC Sequence 2
    ADCIntHandler,                          // ADC Sequence 3
#else
    IntDefaultHandler,	                    // ADC Sequence 0
    IntDefaultHandler,                      // ADC Sequence 1
    IntDefaultHandler,                      // ADC Sequence 2
    IntDefaultHandler,                      // ADC Sequence 3
#endif
    IntDefaultHandler,                      // Watchdog timer
    tmr0_handler,                           // Timer 0 subtimer A
    IntDefaultHandler,                      // Timer 0 subtimer B
    tmr1_handler,                           // Timer 1 subtimer A
    IntDefaultHandler,                      // Timer 1 subtimer B
    tmr2_handler,                           // Timer 2 subtimer A
    IntDefaultHandler,                      // Timer 2 subtimer B
    IntDefaultHandler,                      // Analog Comparator 0
    IntDefaultHandler,                      // Analog Comparator 1
    IntDefaultHandler,                      // Analog Comparator 2
    IntDefaultHandler,                      // System Control (PLL, OSC, BO)
    IntDefaultHandler,                      // FLASH Control
    gpiof_handler,                          // GPIO Port F
    gpiog_handler,                          // GPIO Port G
    gpioh_handler,                          // GPIO Port H
#if defined( BUILD_C_INT_HANDLERS ) || defined( BUILD_LUA_INT_HANDLERS )
    uart2_handler,                          // UART2 Rx and Tx
#else    
    IntDefaultHandler,                      // UART2 Rx and Tx
#endif    
    IntDefaultHandler,                      // SSI1 Rx and Tx
    tmr3_handler,                           // Timer 3 subtimer A
    IntDefaultHandler,                      // Timer 3 subtimer B
    IntDefaultHandler,                      // I2C1 Master and Slave
    IntDefaultHandler,                      // Quadrature Encoder 1
#if defined( BUILD_CAN )
    CANIntHandler,                          // CAN0
#else
    IntDefaultHandler,                      // CAN0
#endif
    IntDefaultHandler,                      // CAN1
    IntDefaultHandler,                      // CAN2
    EthernetIntHandler,                     // Ethernet
#if defined( FORLM3S9B92 ) || defined( FORLM3S9D92 )
    IntDefaultHandler,                      // Hibernate
#if defined( BUILD_USB_CDC )
    USB0DeviceIntHandler,                   // USB0
#else // #if defined( BUILD_USB_CDC )
    IntDefaultHandler,                      // USB0
#endif // #if defined( BUILD_USB_CDC )
    IntDefaultHandler,                      // PWM Generator 3
    IntDefaultHandler,                      // uDMA Software Transfer
    IntDefaultHandler,                      // uDMA Error
    IntDefaultHandler,                      // ADC1 Sequence 0
    IntDefaultHandler,                      // ADC1 Sequence 1
    IntDefaultHandler,                      // ADC1 Sequence 2
    IntDefaultHandler,                      // ADC1 Sequence 3
    IntDefaultHandler,                      // I2S0
    IntDefaultHandler,                      // External Bus Interface 0
    gpioj_handler                           // GPIO Port J    
#else // #if defined( FORLM3S9B92 ) || defined( FORLM3S9D92 )
    IntDefaultHandler                       // Hibernate
#endif // #if defined( FORLM3S9B92 ) || defined( FORLM3S9D92 )
};

//*****************************************************************************
//
// The following are constructs created by the linker, indicating where the
// the "data" and "bss" segments reside in memory.  The initializers for the
// for the "data" segment resides immediately following the "text" segment.
//
//*****************************************************************************
extern unsigned long _etext;
extern unsigned long _data;
extern unsigned long _edata;
extern unsigned long _bss;
extern unsigned long _ebss;

//*****************************************************************************
//
// This is the code that gets called when the processor first starts execution
// following a reset event.  Only the absolutely necessary set is performed,
// after which the application supplied entry() routine is called.  Any fancy
// actions (such as making decisions based on the reset cause register, and
// resetting the bits in that register) are left solely in the hands of the
// application.
//
//*****************************************************************************
void
ResetISR(void)
{
    unsigned long *pulSrc, *pulDest;

    //
    // Copy the data segment initializers from flash to SRAM.
    //
    pulSrc = &_etext;
    for(pulDest = &_data; pulDest < &_edata; )
    {
        *pulDest++ = *pulSrc++;
    }

    //
    // Zero fill the bss segment.  This is done with inline assembly since this
    // will clear the value of pulDest if it is not kept in a register.
    //
    __asm("    ldr     r0, =_bss\n"
          "    ldr     r1, =_ebss\n"
          "    mov     r2, #0\n"
          "    .thumb_func\n"
          "zero_loop:\n"
          "        cmp     r0, r1\n"
          "        it      lt\n"
          "        strlt   r2, [r0], #4\n"
          "        blt     zero_loop");

    //
    // Call the application's entry point.
    //
    main();

    while(1);
}

// Platform specific includes
#include "hw_ints.h"
#include "hw_memmap.h"
#include "hw_types.h"
#include "debug.h"
#include "gpio.h"
#include "interrupt.h"
#include "sysctl.h"
#include "uart.h"

// FIXME: Assumes console is UART, will not be right for USB_CDC

//*****************************************************************************
//
// This is the code that gets called when the processor receives a NMI.  This
// simply enters an infinite loop, preserving the system state for examination
// by a debugger.
//
//*****************************************************************************
static void
NmiSR(void)
{
    MAP_UARTCharPut( uart_base[CON_UART_ID], 'N' );
    MAP_UARTCharPut( uart_base[CON_UART_ID], 'M' );
    MAP_UARTCharPut( uart_base[CON_UART_ID], 'I' );
    //
    // Enter an infinite loop.
    //
    while(1)
    {
      MAP_UARTCharPut( uart_base[CON_UART_ID], '!' );
    }
}

//*****************************************************************************
//
// This is the code that gets called when the processor receives a fault
// interrupt.  This simply enters an infinite loop, preserving the system state
// for examination by a debugger.
//
//*****************************************************************************
static void
FaultISR(void)
{
    //
    // Enter an infinite loop.
    //
   MAP_UARTCharPut( uart_base[CON_UART_ID], 'F' );
   MAP_UARTCharPut( uart_base[CON_UART_ID], 'a' );
   MAP_UARTCharPut( uart_base[CON_UART_ID], 'u' );
   MAP_UARTCharPut( uart_base[CON_UART_ID], 'l' );
   MAP_UARTCharPut( uart_base[CON_UART_ID], 't' );
   while(1)
   {
   }
}

//*****************************************************************************
//
// This is the code that gets called when the processor receives an unexpected
// interrupt.  This simply enters an infinite loop, preserving the system state
// for examination by a debugger.
//
//*****************************************************************************
static void
IntDefaultHandler(void)
{
  MAP_UARTCharPut( uart_base[CON_UART_ID], 'I' );
  MAP_UARTCharPut( uart_base[CON_UART_ID], 'n' );
  MAP_UARTCharPut( uart_base[CON_UART_ID], 't' );
    //
    // Go into an infinite loop.
    //
    while(1)
    {
      MAP_UARTCharPut( uart_base[CON_UART_ID], '*' );
    }
}
